package com.sr.demo.security;

import com.sr.demo.security.auth.*;
import com.sr.demo.security.login.*;
import com.sr.demo.security.password.NuoPasswordEncoder;
import com.sr.demo.security.user.NuoUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;

import javax.servlet.Filter;

/**
 * 配置文件
 * @Author: liushuai
 * @Date: 2021/2/7 22:24
 * @param : * @param null
 * @return :
 **/

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private NuoUserDetailsService nuoUserDetailsService;

    @Autowired
    private NuoAuthenticationProcessingFilter nuoAuthenticationProcessingFilter;

    @Autowired
    private NuoExceptionRedirect nuoExceptionRedirect;
    @Autowired
    private NuoFilterSecurityInterceptor nuoFilterSecurityInterceptor;
    @Autowired
    private NuoAccessDeniedHander nuoAccessDeniedHander;

    @Autowired
    private NuoLoginFailure nuoLoginFailure;
    @Autowired
    private NuoLoginSuccess nuoLoginSuccess;
    /**
     * 从容器中取出 AuthenticationManagerBuilder，执行方法里面的逻辑之后，放回容器
     * @Author: liushuai
     * @Date: 2021/3/11 22:42
     * @param : * @param authenticationManagerBuilder
     * @return :void
     **/
    @Autowired
    public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder.userDetailsService(nuoUserDetailsService);
    }



    protected void configure(HttpSecurity http) throws Exception {
        /**
         * 在 UsernamePasswordAuthenticationFilter 之前添加 JwtAuthenticationTokenFilter
         */
        http.addFilterBefore(nuoFilterSecurityInterceptor, UsernamePasswordAuthenticationFilter.class);
        http.addFilterAt(nuoAuthenticationProcessingFilter, UsernamePasswordAuthenticationFilter.class);
        http.csrf().disable().cors().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and().authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                // 角色校验时，会自动拼接 "ROLE_"
                .anyRequest().authenticated()   // 任何请求,登录后可以访问
                .and().formLogin().loginProcessingUrl("/login")
                .successHandler(nuoLoginSuccess)
                .failureHandler(nuoLoginFailure)
                .and().headers().cacheControl();

        // 处理异常情况：认证失败和权限不足
        http.exceptionHandling().authenticationEntryPoint(nuoExceptionRedirect).accessDeniedHandler(nuoAccessDeniedHander);

    }


    @Bean
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new      UrlBasedCorsConfigurationSource();
        final CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowCredentials(false);
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(urlBasedCorsConfigurationSource);
    }





    public NuoFilterSecurityMetadataSource getNuoFilterSecurityMetadataSource() {
        NuoFilterSecurityMetadataSource sourceService = new NuoFilterSecurityMetadataSource();

        return sourceService;
    }
}
